feat(vcs): add gix-based VCS module with status support - #6
Conversation
Add handoff document, status story, and research doc for implementing gor status using gix (gitoxide) instead of jj-lib. Key advantages of gix over jj-lib: - Already a dependency (no new transitives) - Fully synchronous (no tokio runtime) - No .jj/ directory side effects - Index-based status with lstat caching (fast)
Introduce a new `gor::vcs` module backed by `gix` (gitoxide) for local git operations, beginning with working tree status. - GitRepo::open() discovers repos via gix::discover() (walks up dirs) - GitRepo::status() returns staged, unstaged, untracked, and conflicted files in a single index-based pass - Branch name and upstream tracking ref are extracted from HEAD config - All types derive serde::Serialize for --json output - Zero new dependencies — gix was already in Cargo.toml with "status" feature Phase 0 of the gor status implementation.
|
Warning Review limit reached
Next review available in: 38 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughAdds a ChangesStatus VCS foundation
Estimated code review effort: 3 (Moderate) | ~20 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
Adds a new gor::vcs module that wraps gix to provide a foundation for implementing gor status (Phase 0), along with supporting documentation and typos configuration updates.
Changes:
- Introduced
src/vcs/with status data types and aGitRepowrapper that discovers a repo and computes working tree status viagix. - Exposed the new VCS module from the library (
pub mod vcs) and re-exported key types. - Added design/research docs and updated
_typos.tomlto accommodate new terminology.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| src/vcs/types.rs | Adds VCS status data structures and error type used by the VCS layer. |
| src/vcs/repo.rs | Implements GitRepo::open() and GitRepo::status() using gix status/index APIs. |
| src/vcs/mod.rs | Declares the vcs module and re-exports public surface area. |
| src/lib.rs | Exposes the new vcs module from the crate. |
| HANDOFF.md | Adds a handoff/design note for implementing gor status. |
| docs/research/research-gix-for-gor.md | Adds research documentation mapping gix capabilities to planned commands. |
| docs/issues/status.md | Adds the gor status story/spec and acceptance criteria. |
| _typos.toml | Extends typos allow-list for new tokens encountered in docs/code. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| /// # Errors | ||
| /// | ||
| /// Returns [`VcsError::NotARepository`] if no git repository is found. | ||
| /// Returns [`VcsError::Io`] if an I/O error occurs during discovery. | ||
| pub fn open(path: &Path) -> Result<Self, VcsError> { | ||
| let repo = gix::discover(path).map_err(|e| VcsError::NotARepository(format!("{e}")))?; | ||
| Ok(Self { repo }) | ||
| } |
| /// Get the current branch name, or an empty string if detached HEAD. | ||
| fn get_branch_name(&self) -> String { | ||
| self.repo | ||
| .head() | ||
| .ok() | ||
| .map(|head| head.name().as_bstr().to_string()) | ||
| .filter(|s| !s.is_empty()) | ||
| .unwrap_or_default() | ||
| } |
| }); | ||
| } | ||
| EntryStatus::Conflict { .. } => { | ||
| untracked.push(path); | ||
| } |
|
|
||
| /// Collect staged, unstaged, and untracked changes from the status iterator. | ||
| #[allow(clippy::type_complexity)] | ||
| fn collect_status_changes( | ||
| &self, | ||
| ) -> Result<(Vec<FileStatus>, Vec<FileStatus>, Vec<String>), VcsError> { |
| /// Errors from VCS operations. | ||
| #[derive(Debug, thiserror::Error)] | ||
| #[non_exhaustive] | ||
| pub enum VcsError { | ||
| /// Error when the directory is not a git repository. | ||
| #[error("not a git repository: {0}")] | ||
| NotARepository(String), | ||
|
|
||
| /// A git operation failed with an unexpected error. | ||
| #[error("git operation failed: {0}")] | ||
| Other(String), | ||
|
|
||
| /// IO error during file or network access. | ||
| #[error("I/O error: {0}")] | ||
| Io(#[from] std::io::Error), | ||
| } |
| ## First Steps for the Agent | ||
|
|
||
| 1. `cd /home/kwhatcher/projects/gor-jj-integration` | ||
| 2. Read the two reference docs above | ||
| 3. Start with Phase 0: create the `vcs` module (`mod.rs`, `types.rs`, `repo.rs`) | ||
| 4. Run `cargo build` to validate compilation | ||
| 5. Move to Phase 1: add the CLI arg + dispatch | ||
| 6. Iterate |
Add parentheses to resolve ambiguous link in doc comment — gix::discover is both a function and a module, causing a rustdoc warning error.
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
HANDOFF.md (1)
88-120: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUpdate both status examples to the gix 0.85 platform API.
Repository::status()accepts a progress implementation and returns a configurablestatus::Platform, which is consumed viainto_iter(); it does not takegix::worktree::Statusor exposestaged()/unstaged()/untracked()accessors. (docs.rs)
HANDOFF.md#L88-L120: replace the pseudo-code status construction and collection calls with the Platform + iterator flow used bysrc/vcs/repo.rs.docs/research/research-gix-for-gor.md#L155-L193: correct the quick-reference snippet to usegix::progress::DiscardandPlatform::into_iter().🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@HANDOFF.md` around lines 88 - 120, The status examples in HANDOFF.md (lines 88-120) and docs/research/research-gix-for-gor.md (lines 155-193) use the obsolete gix status API. Update both snippets to match src/vcs/repo.rs: pass gix::progress::Discard to Repository::status, configure and consume the returned status::Platform via into_iter(), and derive staged, unstaged, and untracked entries from the iterator instead of calling accessor methods; leave the surrounding GitRepo/status guidance unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/vcs/repo.rs`:
- Around line 185-187: Update the EntryStatus::Conflict branch in the status
classification logic so conflicted paths are not added to untracked. Remove the
untracked.push(path) behavior while preserving conflict reporting through
get_conflicted_files() and the existing handling of other entry statuses.
- Around line 221-225: Update get_conflicted_files() to sort the collected
conflicted paths and remove duplicates before returning the public list.
Preserve filtering on non-Unconflicted stages and path conversion, ensuring
multiple index stages for the same path produce only one result.
- Around line 76-104: Update get_branch_name and the upstream flow to read the
branch referent via referent_name() instead of Head::name(), returning an empty
string for detached HEAD. Preserve the resolved local branch reference when
calling get_upstream_info, and shorten the full result from
branch_remote_tracking_ref_name() before exposing it as the upstream name.
---
Nitpick comments:
In `@HANDOFF.md`:
- Around line 88-120: The status examples in HANDOFF.md (lines 88-120) and
docs/research/research-gix-for-gor.md (lines 155-193) use the obsolete gix
status API. Update both snippets to match src/vcs/repo.rs: pass
gix::progress::Discard to Repository::status, configure and consume the returned
status::Platform via into_iter(), and derive staged, unstaged, and untracked
entries from the iterator instead of calling accessor methods; leave the
surrounding GitRepo/status guidance unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: b689ada0-0cd8-4b2b-9e62-77e5ceba0585
📒 Files selected for processing (8)
HANDOFF.md_typos.tomldocs/issues/status.mddocs/research/research-gix-for-gor.mdsrc/lib.rssrc/vcs/mod.rssrc/vcs/repo.rssrc/vcs/types.rs
…docs - Fix get_branch_name() to use Head::referent_name() instead of Head::name() (the latter always returns "HEAD", not the branch) - Shorten upstream tracking ref names via FullNameRef::shorten() - Remove conflicted files from the untracked set (already reported separately via get_conflicted_files()) - Sort and deduplicate conflicted file paths (multiple index stages per path) - Update HANDOFF.md and research-gix-for-gor.md code examples to match the gix 0.85 platform iterator API
Implements Phase 0 of the
gor statusfeature.Changes
src/vcs/types.rs— Data types:WorkingTreeStatus,FileStatus,ChangeType,VcsError(allserde::Serialize)src/vcs/repo.rs—GitRepowrapper overgix:open()andstatus()methodssrc/vcs/mod.rs— Module declaration with re-exportssrc/lib.rs— Registeredpub mod vcs_typos.toml— Addedrelato the allow list (false positive)Key design decisions
gixwas already inCargo.tomlwithstatusfeaturegix::statusiterator pass for staged + unstaged + untrackedValidation
cargo build— cleancargo clippy— no warningscargo test --lib— 155/155 passNext steps
Phase 1: CLI arg definition + dispatch for
gor statusPhase 2: Output formatting in
output.rsPhase 3: Integration tests
Summary by CodeRabbit
Documentation
gor statuscommand.New Features
Chores